package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.base.BaseEntity;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumTrackListVo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private VodConstantProperties vodConstantProperties;
	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private VodService vodService;
	@Autowired
	private UserInfoFeignClient  userInfoFeignClient;


	@Override
	public Map<String, Object> uploadTrack(MultipartFile file) {

		HashMap<String, Object> map = new HashMap<>();

		//获取路径
		String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(),file);

		//初始化一个上传客户端对象
		VodUploadClient vodUploadClient = new VodUploadClient(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());

		//云点播的高级功能（付费）：封面 人物流 指定存储地域 指定并发数

		//获取上传请求对象
		VodUploadRequest request = new VodUploadRequest();
		request.setMediaFilePath(tempPath);

		//调用上传方法
		try{
			VodUploadResponse response = vodUploadClient.upload(vodConstantProperties.getRegion(), request);
			log.info("Upload FileId = {}", response.getFileId());


			map.put("mediaFileId",response.getFileId());
			map.put("mediaUrl",response.getMediaUrl());

			return map;
		} catch (Exception e) {
			// 业务方进行异常处理
			log.error("Upload Err", e);
			throw new GuiguException(ResultCodeEnum.FAIL);
		}
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {

		TrackInfo trackInfo = new TrackInfo();
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		trackInfo.setUserId(userId);

		//track_info.order_num 表示声音顺序号 必须来自统一专辑
		LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId())
				.orderByDesc(BaseEntity::getId)
				.last("limit 1");

		TrackInfo one = trackInfoMapper.selectOne(queryWrapper);
		trackInfo.setOrderNum(one == null ? 1 : one.getOrderNum() + 1);

		//需要通过mdeia_file_id 从云点播获取声音对象
		getMediaInfo(trackInfoVo, trackInfo);

		//保存声音数据
		trackInfoMapper.insert(trackInfo);

		//保存声音统计数据
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

		//修改专辑表中的数据 include_track_count(专辑包含声音总数)
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
		albumInfoMapper.updateById(albumInfo);

	}

	private void getMediaInfo(TrackInfoVo trackInfoVo, TrackInfo trackInfo) {
		TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
		trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
		trackInfo.setMediaType(trackMediaInfoVo.getType());
		trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
	}

	public void saveTrackStat(Long trackId, String statPlay) {

		//保存声音统计数据
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statPlay);
		trackStat.setStatNum(0);

		trackStatMapper.insert(trackStat);

	}


	@Override
	public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {

		//	调用mapper层方法
		return trackInfoMapper.selectUserTrackPage(trackListVoPage,trackInfoQuery);
	}


	@Override
	public void removeTrackInfo(Long trackId) {

		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());

		//删除track_stat表 track_info
		this.trackInfoMapper.deleteById(trackId);
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId,trackId));

		//更新 album_info.include_track_count
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
		albumInfoMapper.updateById(albumInfo);

		//跟新序号只需要更新order_num  update track_info set order_num = order_num - 1  where order_num > 52 and album_id = 1 and is_deleted = 0
		trackInfoMapper.updateOrderNum(trackInfo.getOrderNum(),trackInfo.getAlbumId());

		//流媒体的声音删除
		vodService.deleteMedia(trackInfo.getMediaFileId());

	}


	@Override
	public TrackInfo getTrackInfo(Long trackId) {

		TrackInfo trackInfo = this.trackInfoMapper.selectById(trackId);

		return trackInfo;
	}


	/**
	 * 如果修改声音，需要自己获取云点播的音频大小和路径，前端不会传值
	 * @param trackId
	 * @param trackInfoVo
	 */
	@Override
	public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
		//没修改声音：直接修改TrackInfo   如果有声音修改：改变声音存储大小,类型数据等
		TrackInfo trackInfo = this.getById(trackId);

		String mediaFileId = trackInfo.getMediaFileId();

		//不能够方法if方法后 可能会被覆盖掉
		BeanUtils.copyProperties(trackInfoVo,trackInfo);

		if (!trackInfoVo.getMediaFileId().equals(mediaFileId)) {

			//声音修改了 从云点播获取声音对象
			getMediaInfo(trackInfoVo,trackInfo);

			//删除云点播记录
			vodService.deleteMedia(mediaFileId);
		}

		trackInfoMapper.updateById(trackInfo);
	}


	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> pageParam, Long albumId, Long userId) {

		//sql还没写
		IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(pageParam,albumId);

		//获取专辑对象
		AlbumInfo albumInfo = this.albumInfoMapper.selectById(albumId);

		if (userId == null) {  //当前用户未登录  专辑类型分为0101-免费、0102-Vip免费。0103-付费

			//专辑类型不是免费的
			if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {

				//获取专辑免费试听集数
				Integer tracksForFree = albumInfo.getTracksForFree();

				//将大于tracksForFree的IsShowPaidMark设置为true(付费)
				pageInfo.getRecords().stream().filter(item -> item.getOrderNum() > tracksForFree)
						.forEach(info ->  info.setIsShowPaidMark(true));
			}

			return pageInfo;

		}else{  //当前处于登录状态

			//声明一个变量表示是否需要付费
			boolean isNeedPaid = false;

			Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
			Assert.notNull(userInfoVoResult,"用户结果接为空");
			UserInfoVo userInfoVo = userInfoVoResult.getData();
			Assert.notNull(userInfoVo,"用户信息接为空");

			if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())){  //vip免费

				//当前用户是vip但是已经过期了 或者 不是vip
				if(userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date()) || userInfoVo.getIsVip() == 0) {
					//需要付费
					isNeedPaid = true;

				}else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
					isNeedPaid = true;
				}

				//统一处理付费
				if (isNeedPaid) {

					//	处理试听声音，获取需要付费的声音列表
					List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream()
							.filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
							.collect(Collectors.toList());


					//	获取到声音Id 集合列表
					List<Long> trackIdList = albumTrackNeedPaidListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());

					//map中的key=trackId value=0或1  1：免费   0：付费
					Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId,trackIdList);
					Assert.notNull(mapResult,"声音集合不能为空.");
					Map<Long, Integer> map = mapResult.getData();
					Assert.notNull(map,"map集合不能为空.");

					albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
						//	如果map.get(albumTrackListVo.getTrackId()) == 1 已经购买过，则不显示付费标识;
						boolean isBuy = map.get(albumTrackListVo.getTrackId()) == 1 ? false : true;
						albumTrackListVo.setIsShowPaidMark(isBuy);
					});

				}

			}
		}
		return pageInfo;
	}


	@Override
	public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
		//  根据声音Id 获取到当前声音对象
		TrackInfo trackInfo = this.getById(trackId);

		//  获取专辑对象，后续为了获取专辑对应单条声音的价格。
		AlbumInfo albumInfo = this.albumInfoMapper.selectById(trackInfo.getAlbumId());

		//  远程调用 - 用户购买过当前专辑所对应的声音Id集合列表. 19 20;
		Result<List<Long>> trackIdListResult = this.userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
		//  判断
		Assert.notNull(trackIdListResult, "声音Id 集合列表为空");
		List<Long> trackIdList = trackIdListResult.getData();
		Assert.notNull(trackIdList, "声音Id集合为空");

		LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId()).gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
		//  所有的声音Id集合列表 比如：8-54 ;
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(wrapper);

		//  集合排查：获取差集。将购买过的声音排除
		List<TrackInfo> infoList = trackInfoList.stream().filter(track -> {
			//  过滤.
			return !trackIdList.contains(track.getId());
		}).collect(Collectors.toList());

		//  声明集合对象
		List<Map<String, Object>> list = new ArrayList<>();
		//  声明变量:
		BigDecimal trackPrice = albumInfo.getPrice();

        // 判断声音需要付费的集合大小
		int size = infoList.size();

		// 添加本集信息
		if (size >= 0) {
			Map<String, Object> map = new HashMap<>();
			map.put("name", "本集");
			map.put("price", trackPrice);
			map.put("trackCount", 0);
			list.add(map);
		}
		// 根据不同的集数条件添加相应的信息
		if (size > 0 && size <= 50) {
			int[] thresholds = {10, 20, 30, 50};
			for (int threshold : thresholds) {
				if (size > threshold) {
					Map<String, Object> map = new HashMap<>();
					map.put("name", "后" + threshold + "集");
					map.put("price", trackPrice.multiply(new BigDecimal(String.valueOf(threshold))));
					map.put("trackCount", threshold);
					list.add(map);
				} else {
					Map<String, Object> map = new HashMap<>();
					map.put("name", "后" + size + "集");
					map.put("price", trackPrice.multiply(new BigDecimal(String.valueOf(size))));
					map.put("trackCount", size);
					list.add(map);
					break;
				}
			}
		}
		return list;
	}


	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {

		//  创建对象
		List<TrackInfo> trackInfoList = new ArrayList<>();
		//  先根据当前声音Id 获取到声音对象.
		TrackInfo trackInfo = this.getById(trackId);
		//  调用方法获取用户已购买的声音列表.
		Result<List<Long>> trackIdListResult = this.userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
		Assert.notNull(trackIdListResult, "声音Id 集合列表为空");
		List<Long> trackIdList = trackIdListResult.getData();
		Assert.notNull(trackIdList, "声音Id集合为空");
		//  查询用户购买的声音列表.
		if (trackCount > 0) {
			//  select * from track_info where album_id = 1451 and order_num > 6 and id not in (48794,48795) limit 10;
			LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId()).gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
			//  购买声音Id 可能存在，也可能不存在！
			if (!CollectionUtils.isEmpty(trackIdList)) {
				wrapper.notIn(TrackInfo::getId, trackIdList);
			}
			wrapper.last(" limit " + trackCount);
			//  查询数据
			trackInfoList = trackInfoMapper.selectList(wrapper);
		} else {
			//  购买本集
			trackInfoList.add(trackInfo);
		}
		//  返回数据
		return trackInfoList;
	}
}
